// Mesh Format Loader SBS
// (c) jimon game studio

#include "CMeshFormatLoader_SBS.h"

#ifdef JE_SUPPORT_FILEFORMAT_SBS

namespace je
{
	namespace scene
	{
		//! Constructor
		CMeshFormatLoader_SBS::CMeshFormatLoader_SBS()
		{
		}

		//! Destructor
		CMeshFormatLoader_SBS::~CMeshFormatLoader_SBS()
		{
		}

		//! Load Mesh
		jeMesh * CMeshFormatLoader_SBS::LoadMesh(core::IBuffer * DataBuffer,video::IRender * Render)
		{
			DataBuffer->Lock(core::BLT_READ);
			DataBuffer->SetPosition(0);
			DataBuffer->SetStreamWorkMode(true);

			c8 SBS_Format[7] = "sgsbin";

			c8 Current_SBS_Format[7];
			memset(Current_SBS_Format,0,7);

			DataBuffer->Read(Current_SBS_Format,6);
			
			if(memcmp(Current_SBS_Format,SBS_Format,7))
			{
				DataBuffer->UnLock();
				return NULL;
			}

			s32 Reserved[3];
			DataBuffer->Read(Reserved,12);

			s32 VertexType = 0,IndexCount = 0,VertexCount = 0;

			DataBuffer->Read(&VertexType,4);
			DataBuffer->Read(&IndexCount,4);
			DataBuffer->Read(&VertexCount,4);

			video::IHardwareBuffer * IB = Render->CreateHardwareBuffer(video::G3DT_INDEX);
			IB->Lock(core::BLT_WRITE);
			IB->Allocate(IndexCount*sizeof(u16));
			IB->WriteFrom(DataBuffer,IndexCount*sizeof(u16));
			IB->UnLock();
			
			video::IHardwareBuffer * VB = Render->CreateHardwareBuffer(video::G3DT_VERTEX);
			VB->Lock(core::BLT_WRITE);
			VB->Allocate(VertexCount*12*4);
			VB->WriteFrom(DataBuffer,VertexCount*12*4);
			VB->UnLock();

			DataBuffer->UnLock();

			video::IHardwareBufferArray * Arr = Render->CreateHardwareBufferArray();
			Arr->AttachBuffer(VB,video::HBAL_UV,2,4,12*4,0*4);
			Arr->AttachBuffer(VB,video::HBAL_COLOR,4,4,12*4,2*4);
			Arr->AttachBuffer(VB,video::HBAL_NORMAL,3,4,12*4,6*4);
			Arr->AttachBuffer(VB,video::HBAL_POSITION,3,4,12*4,9*4);
			Arr->AttachBuffer(IB,video::HBAL_INDEXES,1,2,2);

			VB->Drop();
			IB->Drop();

			video::jeRenderOperation_Draw * Op = NULL;
			JENEW(Op,video::jeRenderOperation_Draw)
			Op->SetArray(Arr);
			Arr->Drop();

			ISurface * Surface = CreateSurface(Render,video::ROT_DRAW_TRIANGLES,Op);
			Op->Drop();

			jeMesh * Mesh = NULL;
			JENEW(Mesh,jeMesh)
			Mesh->AddSurface(Surface);
			Surface->Drop();

			Mesh->SetName("SBSMesh");
			
			return Mesh;
		}

		//! Save Mesh
		void CMeshFormatLoader_SBS::SaveMesh(core::IBuffer * DataBuffer,jeMesh * Mesh)
		{
			ISurface * Surface = *Mesh->GetSurfaces().getLast();
			video::IHardwareBufferArray * Array = static_cast<video::jeRenderOperation_Draw*>(Surface->GetRenderOperation())->Array;
			video::IHardwareBufferArray::LayerInfo IPos = Array->GetLayerInfo(video::HBAL_POSITION);
			video::IHardwareBufferArray::LayerInfo NPos = Array->GetLayerInfo(video::HBAL_NORMAL);
			video::IHardwareBufferArray::LayerInfo Color = Array->GetLayerInfo(video::HBAL_COLOR);
			video::IHardwareBufferArray::LayerInfo UV = Array->GetLayerInfo(video::HBAL_UV);
			video::IHardwareBufferArray::LayerInfo Index = Array->GetLayerInfo(video::HBAL_INDEXES);

			JEASSERT(IPos.Buffer)
			JEASSERT(Index.Buffer)

			u32 ObjectCount = (u32)IPos.Buffer->GetSize() / IPos.Stride;

			u32 IndexCount = (u32)Index.Buffer->GetSize() / Index.VariableSize;

			struct SBS_Vertex{f32 U,V,R,G,B,A,NX,NY,NZ,X,Y,Z;};

			SBS_Vertex * VSBS = NULL;
			JENEW_A(VSBS,SBS_Vertex,ObjectCount)

			u16 * Indexes = NULL;
			JENEW_A(Indexes,u16,IndexCount)

			if(IPos.Buffer)
			{
				jeVector3df * T = NULL;
				JENEW_A(T,jeVector3df,ObjectCount)
				IPos.Buffer->Lock(core::BLT_READ);
				IPos.Buffer->UnMerge(T,ObjectCount*IPos.VariableSize*IPos.VariablesPerObject,IPos.VariableSize*IPos.VariablesPerObject,IPos.Stride,IPos.Offset);
				IPos.Buffer->UnLock();
				for(u32 i=0;i<ObjectCount;i++)
				{
					VSBS[i].X = T[i].X;
					VSBS[i].Y = T[i].Y;
					VSBS[i].Z = T[i].Z;
				}
				JEDELETE_A(T)
			}

			if(NPos.Buffer)
			{
				jeVector3df * T = NULL;
				JENEW_A(T,jeVector3df,ObjectCount)
				NPos.Buffer->Lock(core::BLT_READ);
				NPos.Buffer->UnMerge(T,ObjectCount*NPos.VariableSize*NPos.VariablesPerObject,NPos.VariableSize*NPos.VariablesPerObject,NPos.Stride,NPos.Offset);
				NPos.Buffer->UnLock();
				for(u32 i=0;i<ObjectCount;i++)
				{
					VSBS[i].NX = T[i].X;
					VSBS[i].NY = T[i].Y;
					VSBS[i].NZ = T[i].Z;
				}
				JEDELETE_A(T)
			}

			if(Color.Buffer)
			{
				video::jeColorARGB32f * T = NULL;
				JENEW_A(T,video::jeColorARGB32f,ObjectCount)
				Color.Buffer->Lock(core::BLT_READ);
				Color.Buffer->UnMerge(T,ObjectCount*Color.VariableSize*Color.VariablesPerObject,Color.VariableSize*Color.VariablesPerObject,Color.Stride,Color.Offset);
				Color.Buffer->UnLock();
				for(u32 i=0;i<ObjectCount;i++)
				{
					VSBS[i].R = T[i].R;
					VSBS[i].G = T[i].G;
					VSBS[i].B = T[i].B;
					VSBS[i].A = T[i].A;
				}
				JEDELETE_A(T)
			}

			if(UV.Buffer)
			{
				jeVector2df * T = NULL;
				JENEW_A(T,jeVector2df,ObjectCount)
				UV.Buffer->Lock(core::BLT_READ);
				UV.Buffer->UnMerge(T,ObjectCount*UV.VariableSize*UV.VariablesPerObject,UV.VariableSize*UV.VariablesPerObject,UV.Stride,UV.Offset);
				UV.Buffer->UnLock();
				for(u32 i=0;i<ObjectCount;i++)
				{
					VSBS[i].U = T[i].X;
					VSBS[i].V = T[i].Y;
				}
				JEDELETE_A(T)
			}

			if(Index.Buffer)
			{
				u8 * IndexesTemp = NULL;
				JENEW_A(IndexesTemp,u8,IndexCount*Index.VariableSize)

				Index.Buffer->Lock(core::BLT_READ);
				Index.Buffer->UnMerge(IndexesTemp,IndexCount*Index.VariablesPerObject*Index.VariableSize,Index.VariablesPerObject*Index.VariableSize,Index.Stride,Index.Offset);
				Index.Buffer->UnLock();

				core::RemapArray(IndexesTemp,Index.VariableSize,IndexCount,(u8*)Indexes,sizeof(u16));

				JEDELETE_A(IndexesTemp)
			}

			DataBuffer->Lock(core::BLT_WRITE);

			DataBuffer->Allocate(6+12+12+2*IndexCount+ObjectCount*sizeof(SBS_Vertex));
			DataBuffer->SetPosition(0);
			DataBuffer->SetStreamWorkMode(true);

			c8 SBS_Format[7] = "sgsbin";
			DataBuffer->Write(SBS_Format,6);

			s32 Reserved[3];
			memset(Reserved,0,12);
			DataBuffer->Write(Reserved,12);

			s32 VertexType = 4;
			DataBuffer->Write(&VertexType,4);
			DataBuffer->Write(&IndexCount,4);
			DataBuffer->Write(&ObjectCount,4);

			DataBuffer->Write(Indexes,IndexCount*2);
			JEDELETE_A(Indexes)
			
			DataBuffer->Write(VSBS,ObjectCount*sizeof(SBS_Vertex));
			JEDELETE_A(VSBS)

			DataBuffer->UnLock();
		}

		//! Return true if mesh loader can work with this data
		u1 CMeshFormatLoader_SBS::CanWorkWithThis(core::IBuffer * DataBuffer)
		{
			DataBuffer->Lock(core::BLT_READ);
			DataBuffer->SetPosition(0);
			DataBuffer->SetStreamWorkMode(true);
			c8 SBS_Format[7] = "sgsbin";
			c8 Current_SBS_Format[7];
			memset(Current_SBS_Format,0,7);
			DataBuffer->Read(Current_SBS_Format,6);
			DataBuffer->UnLock();
			return memcmp(Current_SBS_Format,SBS_Format,7) ? false : true;
		}
	}
}

#endif
